home *** CD-ROM | disk | FTP | other *** search
Wrap
/* * $Header: /usr/src/Projects/codeblue/codeblue.c,v 1.1 2001/08/02 20:40:01 root Exp root $ * ****************************************************************************************** * -[ G O D B L E S S A M E R I C A ]- * ****************************************************************************************** * * CodeBlue v5 by Michael (mystic@tenebrous.com) * This software is freely distributable under the terms of the GNU/GPL. * Please see file 'COPYING' * * Copyright(c) 2001 mystic@tenebrous.com * In cooporation with worm.jungnickel.com. * * CodeBlue is a simple program which scans an Apache access log file, * searching for hosts who requested documents notoriously associated with * malicious worms such as CodeRed and Nimda, and attempts to email these hosts * with a warning about their infection and where to find more information. * * This is an attempt to increase the awareness of malicious worms * and eventually elliminate their existence. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author contact: Michael <mystic@tenebrous.com> * * $Log: codeblue.c,v $ * Revision 1.1 2001/08/02 20:40:01 root * Initial revision * ******************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <signal.h> #include <unistd.h> #include <fcntl.h> #include <time.h> #include <ctype.h> #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> /* * The path to your system whois binary */ #define WHOIS_PATH "/usr/bin/whois" /* * This variable holds the 'triggers' to search for when scanning * the Apachge log file.. */ #define MAX_TRIGGERS 3 /* specifies number of triggers we have in trigger (below) */ static const char trigger[MAX_TRIGGERS][56] = { "GET /default.ida?NNNNNN", /* Code Red I */ "GET /default.ida?XXXXXX", /* Code Red II */ "GET /scripts/root.exe" /* Nimda */ }; /* * Macros - Please do not change */ #define SMTP_SUBJECT "You may be infected [CB]" #define SMTP_USER "postmaster" #define SMTP_PORT 25 #define SMTP_TIMEOUT 5 #define SEND_FL 0x0 /* send flags */ #define RECV_FL 0x0 /* recv flags */ /* * Flags to be used in command line parsing.. */ unsigned short flags = 0; /* global flag reference */ #define FL_SENDQUERY (1<<1) #define FL_WHOIS (1<<2) #define FL_BEQUIET (1<<3) /* * * Global Variables Section * */ /* * This is the content of our warning email: * Please do not change! */ static const char *message = "This message was automatically generated by CodeBlue. Please do not reply.\n\n\n" "\tAfter scanning our web-server log files, we have noticed that your host,\n" "%s, may very well be infected with a malicious worm.\n" "\n" "\tThe following is a line from our Apache log file that validates the infection of\n" "%s:\n" "\n%s\n\n" "This worm appears to be: %s\n\n" "\tIt is HIGHLY recommended that you remove this worm at once! To find information\n" "on how to remove this worm and prevent future attacks, please visit\n" "www.dshield.org and www.incidents.org.\n\n" "Thank you\n" "Sincerely,\n" "The Code-Blue team\n" "\r\n.\r\n"; /* this is needed to signify end of input */ char infected_host[512]; /* Stores address of infected host */ char logline[512]; /* Stores GET line from access log */ char reply[512]; /* stores reply email address */ static unsigned int filepos = 0; /* stores file position */ FILE *log; /* log file stream */ FILE *fp; /* access_log file stream */ int hostswarned = 0, hostsnwarned = 0; /* Keeps tracks of how many hosts warned/not warned */ int lastresponse; /* stores last SMTP response */ char hostlist[2048 * 512]; /* stores hosts as we warn them */ char wormstyle[32]; /* stores name of worm */ int mainsock; /* our main socket descriptor */ char whoispath[512] = "/usr/bin/whois"; /* Path to whois program */ /****************************************************************/ /* * More macros */ #define TRUE 1 #define FALSE 0 #define SUCCESS 0 #define FAILURE 1 /********************************************************************* * FUNCTION PROTOTYPES GO HERE */ void banner(void); void usage(char *); void DieWithHelp(char *); void DieWithRequire(char *); void signal_init(void); void signal_handler(int); int Close(int); int resolv(const char *, struct sockaddr_in *); char *chop(char *); void invalid_reply(char *); int get_smtp_reply(int); int send_smtp(int, char *); int smtp_connect(char *); int send_email(void); int scan_file(FILE *); int send_jung_query(char *, int); char *get_contact(char *); /********************************************************************* * Prints banner header */ void banner(void) { printf("[ CodeBlue v4.2 by Michael (mystic@tenebrous.com) ]\n\n"); } /********************************************************************* * Prints usage information */ void usage(char *prog) { printf("\nUsage: %s [options] <access-log-file>\n" "Example: %s /var/www/logs/access_log\n", prog, prog); printf("\nTry %s --help for a list of options\n\n", prog); exit(1); } /********************************************************************* * Prints help menu */ void DieWithHelp(char *prog) { printf("\nUsage: %s [options] <access-log-file>\n" "Example: %s /var/www/logs/access_log\n", prog, prog); printf("\nOptions can be any of the following:\n" " -e <user@mydomain.com> Specify the return-to address in each email\n" " - Default is postmaster@yourhostname\n" " -q Send each infected hostname to the Nimda Registry \n " " at worm.jungnickel.com. This is highly recommended!\n" " -s Silent mode - not output goes to stdout\n" "--help Print this help menu and exit.\n"); printf("\n"); exit(0); } /********************************************************************* * An option was specified that required an argument - but had non */ void DieWithRequire(char *arg) { fprintf(stderr, "[ ERROR: %s requires an argument\n", arg); exit(1); } /********************************************************************* * Handles signals we specify later on */ void signal_handler(int signo) { time_t tp = time(NULL); switch (signo) { case SIGINT:{ fprintf(stderr, "\n[***] Caught SIGINT; Cleaning up...\n"); printf ("[***] %d infected hosts were successfully warned, and %d were not.\n", hostswarned, hostsnwarned); fprintf (log, "[***] %d infected hosts were successfully warned, and %d were not.\n", hostswarned, hostsnwarned); fprintf(log, "\n[ LOG END - %s ]\n", chop(ctime(&tp))); fclose(log); exit(1); } case SIGPIPE:{ if(!(flags & FL_BEQUIET)) fprintf(stderr, "[ ERROR: Caught SIGPIPE, skipping this host...\n"); fprintf(log, "[ ERROR: Caught SIGPIPE, skipping this host...\n"); signal_init(); Close(mainsock); scan_file(fp); } default:{ fprintf(stderr, "\n[ SIGNAL: %s; Attempting to continue...\n", sys_siglist[signo]); fprintf(log, "\n..... SIGNAL: %s; Attempting to continue...\n", sys_siglist[signo]); Close(mainsock); signal_init(); scan_file(fp); } } } /* * siginal_init: * sets up all the signals we'd like * to handle specially */ void signal_init(void) { struct sigaction sa_old, sa_new; /* signal handling */ sa_new.sa_handler = signal_handler; sigemptyset(&sa_new.sa_mask); sa_new.sa_flags = 0; sigaction(SIGINT, &sa_new, &sa_old); sigaction(SIGPIPE, &sa_new, &sa_old); } /********************************************************************* * Our close() wrapper */ int Close(int sd) { return (close(sd)); } /********************************************************************* * This attempts to resolve a hostname, and stores * the IP address in a sin structure on success */ int resolv(const char *name, struct sockaddr_in *addr) { struct hostent *host; memset(addr, 0, sizeof(struct sockaddr_in)); addr->sin_addr.s_addr = inet_addr(name); if (addr->sin_addr.s_addr == -1) { if ((host = gethostbyname(name)) == NULL) return -1; addr->sin_family = host->h_addrtype; memcpy((caddr_t) & addr->sin_addr, host->h_addr, host->h_length); } return 0; } /********************************************************************* * Returns str without the trailing \n character */ char *chop(char *str) { int i = 0; while (str[i]) { if (str[i] == '\n') str[i] = '\0'; i++; } return str; } /********************************************************************* * prints invalid SMTP reply */ void invalid_reply(char *msg) { fflush(stdout); fprintf(stderr, "[ Bad SMTP reply: %s\n", msg); fprintf(log, "..... Bad SMTP reply: %s\n", msg); return; } /********************************************************************* * fetches a reply from the SMTP server */ int get_smtp_reply(int sd) { char response[1024]; char reply_message[1024]; /* will hold the reply, minus the numeric prefix */ int i = 0; int numeric; fd_set rset; struct timeval tv; int elapsed = 0; /* * We'll loop infinately, receiving * 1 byte at a time until we receive a carriage return * or line-feed character, signifying the end of the output */ /* * set timeout on our socket descriptor */ tv.tv_sec = SMTP_TIMEOUT; tv.tv_usec = 0; FD_ZERO(&rset); FD_SET(sd, &rset); while (TRUE) { if (select((sd + 1), &rset, NULL, NULL, &tv) < 0) { if (errno != EINPROGRESS) { fprintf(stderr, "[ ERROR: select() failed: %s\n", strerror(errno)); return -1; } } if (recv(sd, (int *) &response[i], 1, RECV_FL) < 0) { if (errno == EAGAIN) { if (elapsed >= SMTP_TIMEOUT) { fprintf(stderr, "[ ERROR: operation timed out\n"); fprintf(log, "..... ERROR: operation timed out\n"); return -1; } elapsed++; usleep(SMTP_TIMEOUT * 10000); continue; } else { if (!(flags & FL_BEQUIET)) fprintf(stderr, "[ ERROR: recv() failed: %s\n", strerror(errno)); fprintf(log, "..... ERROR: recv() failed: %s\n", strerror(errno)); return -1; } } if ((response[i] == '\n') || ((response[i] == '\n') && (response[i + 1] == '\n'))) break; i++; } /* * this will store the numeric portion of the reply * into numeric: */ numeric = atoi((strtok(response, " "))); /* * This will copy the reply, without * the numeric prefix into reply_message */ for (i = 4; i < (strlen(response) + 1); i++) { if ((response[i] == '\0') || (response[i] == '\n') || (response[i] == '\r')) break; reply_message[i - 4] = response[i]; } response[i] = '\0'; /* * Now let's check the numeric reply * replies based on RFC 821 (SMTP) */ switch (numeric) { /* * These are replies we can handle (Non-error) */ case 220: /* Service Ready */ case 221:{ lastresponse = numeric; return 0; } /* Service closing connection */ case 250: /* Requested mail action okay, completed */ case 251: /* User not local, will forward to <forward-path> */ case 354: /* Start mail intput, end with <CRLF>.<CRLF> */ break; default:{ invalid_reply(reply_message); return -1; } } lastresponse = numeric; return 0; } /********************************************************************* * sends the SMTP string * we're gonna poll the socket.. fyi */ int send_smtp(int sd, char *buffer) { if (send(sd, buffer, strlen(buffer), 0) < 0) return -1; if (lastresponse != 354) { if (get_smtp_reply(sd) < 0) return -1; } return SUCCESS; } /********************************************************************* * smtp_connect: * creates a socket and connects to it, * returning the socket file descriptor. */ int smtp_connect(char *hostname) { struct sockaddr_in sin; fd_set rset; struct timeval tv; int ttl = 255; /* * This will resolve the hostname, if possible, * and store the 32bit address in our sin structure */ if (resolv(hostname, &sin) < 0) { fprintf(stderr, "[ ERROR: could not resolve %s\n", hostname); fprintf(log, "..... ERROR: could not resolve %s\n", hostname); return -1; } sin.sin_family = AF_INET; sin.sin_port = htons(SMTP_PORT); if ((mainsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { fprintf(stderr, "[ ERROR: socket() failed: %s\n", strerror(errno)); fprintf(log, "..... ERROR: socket() failed: %s\n", strerror(errno)); return -1; } /* * Set socket non-blocking */ fcntl(mainsock, F_SETFL, O_NONBLOCK); if (connect (mainsock, (struct sockaddr *) &sin, sizeof(struct sockaddr_in)) < 0) { if (errno == EINPROGRESS); /* do nothing */ else { fprintf(stderr, "[ ERROR: connect() failed: %s\n", strerror(errno)); fprintf(log, "..... ERROR: connect() failed: %s\n", strerror(errno)); Close(mainsock); return -1; } } /* * set timeout on our socket descriptor */ tv.tv_sec = SMTP_TIMEOUT; tv.tv_usec = 0; FD_ZERO(&rset); FD_SET(mainsock, &rset); while (TRUE) { if (select((mainsock + 1), &rset, NULL, NULL, &tv) != 1) { if (errno == EINPROGRESS); else { fprintf(stderr, "[ ERROR: select() failed: %s\n", strerror(errno)); Close(mainsock); return -1; } } break; } /* * set socket options... */ setsockopt(mainsock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); /* * return our socket descriptor */ return mainsock; } /********************************************************************* * sends email */ int send_email(void) { int sd; char buffer[2048]; char *email; char *user = malloc(sizeof(char) * 512); char *host = malloc(sizeof(char) * 512); /* * get technical contact: */ if (flags & FL_WHOIS) { if (!(flags & FL_BEQUIET)) printf("[ Finding technical contact information... "); fprintf(log, "..... Finding technical contact information... "); if ((email = get_contact(infected_host)) == NULL) { printf("not found!\n"); fprintf(log, "not found!\n"); } if (!(flags & FL_BEQUIET)) printf("found!\n"); user = strtok(email, "@"); user[strlen(user)] = '\0'; host = strtok(NULL, "@"); host[strlen(host)] = '\0'; if (!(flags & FL_BEQUIET)) printf("[ Emailing %s@%s in regards to %s\n", user, host, infected_host); fprintf(log, "..... Emailing %s@%s in regards to %s\n", user, host, infected_host); } else { strcpy(user, SMTP_USER); strcpy(host, infected_host); } if ((sd = smtp_connect(host)) < SUCCESS) return -1; /* Step 0 - Get initial server response */ get_smtp_reply(sd); /* Step 1 - Send HELO */ sprintf(buffer, "HELO localhost\r\n"); if (send_smtp(sd, buffer) < SUCCESS) return -1; /* Step 2 - MAIL FROM */ sprintf(buffer, "MAIL FROM: <%s>\r\n", reply); if (send_smtp(sd, buffer) < SUCCESS) return -1; /* Step 3 - RCPT TO */ sprintf(buffer, "RCPT TO: <%s>\r\n", user); if (send_smtp(sd, buffer) < SUCCESS) return -1; /* Step 4 - DATA */ sprintf(buffer, "DATA\r\n"); if (send_smtp(sd, buffer) < SUCCESS) return -1; /* Step 5 - To: */ sprintf(buffer, "To: infected host <%s@%s>\r\n", SMTP_USER, infected_host); if (send_smtp(sd, buffer) < SUCCESS) return -1; /* Step 6 - Subject: */ sprintf(buffer, "Subject: %s\r\n", SMTP_SUBJECT); if (send_smtp(sd, buffer) < SUCCESS) return -1; /* Step 7 - make High Priority */ sprintf(buffer, "X-Priority: 1\r\nX-MSMail-Priority: High\r\n"); if (send_smtp(sd, buffer) < SUCCESS) return -1; /* Step 8 - actual msesage */ sprintf(buffer, message, infected_host, infected_host, logline, wormstyle); if (send_smtp(sd, buffer) < SUCCESS) return -1; /* Step 9 - QUIT */ sprintf(buffer, "QUIT\r\n"); if (send_smtp(sd, buffer) < SUCCESS) return -1; /* * Close our socket descriptor and return */ Close(sd); free(host); free(user); return SUCCESS; } /********************************************************************* * scans apache access log file for infected CodeRed (1/2) hosts */ int scan_file(FILE * fp) { char buffer[1024]; int i = 0; int found_infected = 0; /* BOOL */ struct sockaddr_in sin; fseek(fp, filepos, SEEK_SET); while (!feof(fp)) { i = 0; /* reset i */ found_infected = 0; /* reset found_infected */ fgets(buffer, 1024, fp); filepos = ftell(fp); for (; i < MAX_TRIGGERS; i++) { if (strstr(buffer, trigger[i]) != NULL) { found_infected = 1; /* we've found an infected host */ if (flags & FL_SENDQUERY) send_jung_query(infected_host, i); switch (i) { case 0:{ strcpy(wormstyle, "Code-Red 1"); break; } case 1:{ strcpy(wormstyle, "Code-Red 2"); break; } case 2:{ strcpy(wormstyle, "Nimda"); break; } default:{ strcpy(wormstyle, "Unknown"); break; } } } } if (found_infected == 1) { strcpy(logline, buffer); strcpy(infected_host, strtok(buffer, " ")); if (resolv(infected_host, &sin) < 0) { if (!(flags & FL_BEQUIET)) fprintf(stderr, "[ ERROR: Couldn't resolve %s: %s\n", infected_host, strerror(errno)); } else { strcpy(infected_host, inet_ntoa(sin.sin_addr)); } if (!(flags & FL_BEQUIET)) printf ("\n\n[ (%s) Infected host [%s] - Sending email...\n", wormstyle, infected_host); fprintf(log, "\n\n..... (%s) Infected host [%s] - Sending email...\n", wormstyle, infected_host); if (strstr(hostlist, infected_host) != NULL) { if (!(flags & FL_BEQUIET)) fprintf(stderr, "[ Host already processed\n"); fprintf(log, "..... Host already processed\n"); continue; } if (send_email() < SUCCESS) { if (!(flags & FL_BEQUIET)) fprintf(stderr, "[ A previous error prevented us from emailing %s\n", infected_host); fprintf(log, "..... A previous error prevented us from emailing %s\n", infected_host); hostsnwarned++; /* hosts not warned */ } else { if (!(flags & FL_BEQUIET)) printf("[ Host was successfully warned via email\n"); fprintf(log, "..... Host was successfully warned via email\n"); hostswarned++; strcat(hostlist, infected_host); /* add host to list */ } } } return 0; } /********************************************************************* * Code to retrieve technical contact email for specified * address.. We'll then email that address as well if the user * specified -w */ char *get_contact(char *domain) { FILE *fp; char buffer[1024], path[1024], *email = NULL; /* * Mold the path + args for whois */ sprintf(path, "%s %s\n", WHOIS_PATH, domain); /* * Open a pipe to our whois binary: */ if ((fp = popen(path, "r")) == NULL) { fprintf(stderr, "[ ERROR: Can't execute %s: %s\n", WHOIS_PATH, strerror(errno)); fprintf(log, "..... ERROR: Can't execute %s: %s\n", WHOIS_PATH, strerror(errno)); return NULL; } /* * Go through the output, looking for contact email */ while (!feof(fp)) { fgets(buffer, 1024, fp); /* * Search string for U.S. style whois responses: */ if ((strstr(buffer, "Technical") != NULL) || (strstr(buffer, "Coordinator") != NULL)) { fgets(buffer, 1024, fp); email = strtok(buffer, " "); email = strtok(NULL, " "); email = strtok(NULL, " "); email = strtok(NULL, " "); break; /* email should hold the proper address now */ } /* * Search string for non-U.S. style whois responses: */ if ((strstr(buffer, "Email:") != NULL) || (strstr(buffer, "e-mail:") != NULL)) { email = strtok(buffer, " "); email = strtok(NULL, " "); break; /* email should hold the proper address now */ } } fclose(fp); return chop(email); } /********************************************************************* * Queries the web-server at worm.jungnickel.com, * adding each infected host to their database.. */ int send_jung_query(char *host, int type) { struct sockaddr_in sin; char wormtype[8]; char querystring[512]; char recvbuf[8]; int sock; /* * Their CGI understands "codered" and "nimda" * as of this release */ switch (type) { case 0: case 1:{ strcpy(wormtype, "codered"); break; } case 2:{ strcpy(wormtype, "nimda"); break; } } wormtype[strlen(wormtype)] = '\0'; memset(&sin, 0, sizeof(struct sockaddr_in)); if (!(flags & FL_BEQUIET)) printf("\n[ Querying worm.jungnickel.com 'Nimda Registry': "); fprintf(log, "\n..... Querying worm.jungnickel.com 'Nimda Registry': "); if (resolv("worm.jungnickel.com", &sin) < 0) { printf(" failed.\n\n"); return -1; } sin.sin_family = AF_INET; sin.sin_port = htons(80); /* HTTP */ if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { if (!(flags & FL_BEQUIET)) printf(" failed.\n\n"); return -1; } if (connect(sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) { if (!(flags & FL_BEQUIET)) printf(" failed.\n\n"); return -1; } sprintf(querystring, "GET ?action=submit&type=%s&ip=%s\r\n", wormtype, host); if (send(sock, querystring, strlen(querystring), 0) < 0) { if (!(flags & FL_BEQUIET)) printf(" failed.\n\n"); return -1; } if (recv(sock, recvbuf, 7, 0) < 0) { printf(" failed.\n\n"); return -1; } recvbuf[strlen(recvbuf)] = '\0'; if (!(flags & FL_BEQUIET)) printf("\n[ worm.jungnickel.com says: %s\n", chop(recvbuf)); fprintf(log, "\n..... worm.jungnickel.com says: %s\n", chop(recvbuf)); Close(sock); return 0; } /********************************************************************* * Hmm. I wonder what main() does... */ int main(int argc, char **argv) { char logfile[1024]; char accesslog[1024]; char timebuf[256]; char hostname[256]; time_t tp, start, finish, total; struct tm *tms; /*uid_t userid;*/ /* * We'll first check the userid.. * CodeBlue must be run as root for security reasons. */ /* if ((userid = getuid()) != 0) { fprintf(stderr, "uid %d is invalid!\n", userid); fprintf(stderr, "This program MUST be run as root\n"); exit(1); } */ /* * Initialize signal handling */ signal_init(); /* * let's make stdout, stderr, and log unbuffered.. */ setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); /* * Display banner */ banner(); /* * Make sure we have at least 3 arguments */ if ((argv[1]) && (strcmp(argv[1], "--help") == 0)) DieWithHelp(argv[0]); if (argc < 2) usage(argv[0]); /* * We'll set the reply-to address to a default value * based on hostname: */ gethostname(hostname, 256); strcat(reply, "postmaster@"); strcat(reply, hostname); /******************************************************/ /* * Parse command line, storing flags in the 'flags' global variable */ if (argc > 2) { int i = 0; while (i < argc) { if (strcmp(argv[i], "--help") == 0) DieWithHelp(argv[0]); /* --help */ if (argv[i][0] == '-') switch (argv[i][1]) { case 'e':{ /* return email address */ if ((!argv[i + 1]) || (argv[i + 1][0] == '-')) DieWithRequire(argv[i]); strcpy(reply, argv[i + 1]); break; } case 'p':{ /* path to whois binary */ if ((!argv[i + 1]) || (argv[i + 1][0] == '-')) DieWithRequire(argv[i]); strcpy(whoispath, argv[i + 1]); break; } case 'q':{ /* send query to Nimda Registry */ flags |= FL_SENDQUERY; break; } case 'w':{ /* whois lookup technical contact */ flags |= FL_WHOIS; break; } case 's':{ /* silent mode */ flags |= FL_BEQUIET; break; } default:{ /* dunno */ fprintf(stderr, "[ ERROR: Unrecognized option: %s\n", argv[i]); break; } } i++; } } strcpy(accesslog, argv[argc - 1]); /* * Validate email address: */ if (reply) { int i = 0; int tally = 0; while (reply[i]) { if ((reply[i] == '@') || (reply[i] == '.')) tally++; i++; } if (tally < 2) { fprintf(stderr, "[ ERROR: %s does not appear to be valid email address\n", reply); return -1; } } /* * local fp will point to the specified access log * Let's open that now and scan it.. */ if ((fp = fopen(accesslog, "r")) == NULL) { fprintf(stderr, "[ ERROR: Couldn't open %s for reading: %s\n", accesslog, strerror(errno)); return FAILURE; } /* * Let's build the name for our logfile, based on date. * It will be opened for append. */ tp = time(NULL); tms = localtime(&tp); strftime(timebuf, 128, "%b-%d-%G", tms); sprintf(logfile, "codeblue-scan-%s.log", timebuf); /* * the global FILE stream log will be opened for append */ if ((log = fopen(logfile, "a")) == NULL) { fprintf(stderr, "[ ERROR: Couldn't open %s for append: %s\n", logfile, strerror(errno)); return FAILURE; } setvbuf(log, NULL, _IONBF, 0); tp = time(NULL); fprintf(log, "[ LOG START - %s ]\n", chop(ctime(&tp))); start = time(NULL); /* set start time */ printf("[ Scanning %s for infected hosts\n", accesslog); if (scan_file(fp) < SUCCESS) return FAILURE; finish = time(NULL); /* finish time */ total = (finish - start); /* total time elapsed */ printf("\n[***] Task completed in %d minutes, %d seconds!\n", (int) (total / 60), (int) (total % 60)); printf ("[***] %d infected hosts were were successfully warned, and %d were not\n", hostswarned, hostsnwarned); tp = time(NULL); fprintf(log, "[ LOG END - %s ]\n", chop(ctime(&tp))); fclose(fp); fclose(log); return SUCCESS; } /* * Please do not alter these. Thank you for your respect. */ static const char rcsid[] = { "$Creator: Michael Behan (mystic@tenebrous.com $" }; static const char rcsid2[] = { "$Copyright: (c) 2001 mystic@tenebrous.com $" };